package zero.tech.games.dn.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import zero.tech.core.data.KeyVal;
import zero.tech.games.dn.data.DnConfig;
import zero.tech.games.dn.data.entity.Card;
import zero.tech.games.dn.data.entity.DnOut;
import zero.tech.games.dn.data.entity.PlayerData;
import zero.tech.games.dn.data.entity.SpecialNiu;

public class CardUtil {
	private static final int ER_VAL=15;
	private static final int A_VAL=14;
	public static List<Card> deckWithoutJoker(){
		List<Card> list=new ArrayList<Card>();
		for(int i=1;i<=4;i++) {
			for(int j=3;j<=15;j++) {
				Card card=new Card(i,j);
				list.add(card);
			}
		}
		return list;
	}

	public static DnOut calDnOut(List<Card> cards,DnConfig dnConfig) {
		DnOut dnOut=calSpecialNiu(cards,dnConfig);
		if(dnOut!=null) {
			return dnOut;
		}
		List<DnOut> result=new ArrayList<>();
		List<Card> tmp=new ArrayList<>();
		tmp.addAll(cards);
		List<List<Card>> out = new ArrayList<List<Card>>();
		Combine.combine(tmp, out,3);
		
		//开始计算所有组合能够组成牛的
		for(List<Card> combine:out) {
			List<Card> temp=new ArrayList<>();
			temp.addAll(cards);
			int cardnum=0;
			for(Card card:combine) {
				int tmpnum=card.getCardNum();
				if(tmpnum==ER_VAL) {
					tmpnum=2;
				}else if(tmpnum==A_VAL){
					tmpnum=1;
				}else if(tmpnum>=10&&tmpnum<14){
					tmpnum=10;
				}
				cardnum+=tmpnum;
			}
			if(cardnum%10==0) {
				//能够组成牛,计算牛几
				temp.removeAll(combine);
				int niu=0;
				for(Card card:temp) {
					int tmpnum=card.getCardNum();
					if(tmpnum==ER_VAL) {
						tmpnum=2;
					}else if(tmpnum==A_VAL){
						tmpnum=1;
					}else if(tmpnum>=10&&tmpnum<14){
						tmpnum=10;
					}
					niu+=tmpnum;
				}
				niu=niu%10;
				if(niu==0) {
					niu=10;
				}
				result.add(new DnOut(niu, cards));
			}
		}
		
		if(result.isEmpty()) {
			//不能组成牛
			dnOut=new DnOut(0,cards);
			return dnOut;
		}else {
			//能够组成牛
			Collections.sort(result,new Comparator<DnOut>() {
				
				@Override
				public int compare(DnOut o1, DnOut o2) {
					return o2.getNiu()-o1.getNiu();
				}
			});
			dnOut=result.get(0);
			return dnOut;
		}
	}

	private static DnOut calSpecialNiu(List<Card> cards, DnConfig dnConfig) {
		DnOut dnOut=null;
		if(dnOut==null&&dnConfig.getNiu18_multiple()!=0) {
			dnOut=tonghuashunniu(cards);
		}
		if(dnOut==null&&dnConfig.getNiu17_multiple()!=0) {
			dnOut=zhadanniu(cards);
		}
		if(dnOut==null&&dnConfig.getNiu16_multiple()!=0) {
			dnOut=wuxiaoniu(cards);
		}
		if(dnOut==null&&dnConfig.getNiu15_multiple()!=0) {
			dnOut=wuhuaniu(cards);
		}
		if(dnOut==null&&dnConfig.getNiu14_multiple()!=0) {
			dnOut=huluniu(cards);
		}
		if(dnOut==null&&dnConfig.getNiu13_multiple()!=0) {
			dnOut=tonghuaniu(cards);
		}
		if(dnOut==null&&dnConfig.getNiu12_multiple()!=0) {
			dnOut=shunziniu(cards);
		}
		if(dnOut==null&&dnConfig.getNiu11_multiple()!=0) {
			dnOut=yinniu(cards);
		}
		return dnOut;
	}

	private static DnOut yinniu(List<Card> cards) {
		int hua=0;
		int shi=0;
		for(Card card:cards) {
			if(card.getCardNum()>10&&card.getCardNum()<14) {
				hua+=1;
			}
			if(card.getCardNum()==10) {
				shi+=1;
			}
		}
		if(hua==4&&shi==1) {
			return new DnOut(SpecialNiu.YIN_NIU, cards);
		}
		return null;
	}

	private static DnOut shunziniu(List<Card> cards) {
		Map<Integer,Integer> numMap=numMap(cards);
		 if(numMap.size()==cards.size()) {
			 List<Integer> nums=new ArrayList<>();
			 nums.addAll(numMap.keySet());
			 List<List<Integer>> list=shun(nums, 5);
			 if(!list.isEmpty()) {
				 return new DnOut(SpecialNiu.SHUNZI_NIU, cards);
			 }
		 }
		return null;
	}

	private static DnOut tonghuaniu(List<Card> cards) {
		boolean tonghua=true;
		int hua=cards.get(0).getCardColor();
		for(Card card:cards) {
			if(card.getCardColor()!=hua) {
				tonghua=false;
				break;
			}
		}
		if(tonghua) {
			return new DnOut(SpecialNiu.TONGHUA_NIU, cards);
		}
		return null;
	}

	private static DnOut huluniu(List<Card> cards) {
		Map<Integer,Integer> numMap=numMap(cards);
		if(numMap.containsValue(3)&&numMap.containsValue(2)) {
			return new DnOut(SpecialNiu.HULU_NIU, cards);
		}
		return null;
	}

	private static DnOut wuhuaniu(List<Card> cards) {
		boolean allhua=true;
		for(Card card:cards) {
			if(card.getCardNum()<=10||card.getCardNum()>13) {
				allhua=false;
				break;
			}
		}
		if(allhua) {
			return new DnOut(SpecialNiu.WUHUA_NIU, cards);
		}
		return null;
	}

	private static DnOut wuxiaoniu(List<Card> cards) {
		int total_num=0;
		for(Card card:cards) {
			int num=card.getCardNum();
			if(num==ER_VAL) {
				num=2;
			}
			if(num==A_VAL) {
				num=1;
			}
			total_num+=num;
		}
		if(total_num<=10) {
			return new DnOut(SpecialNiu.WUXIAONIU, cards);
		}
		return null;
	}

	private static DnOut zhadanniu(List<Card> cards) {
		Map<Integer,Integer> numMap=numMap(cards);
		if(numMap.containsValue(4)) {
			return new DnOut(SpecialNiu.ZHADAN_NIU, cards);
		}
		return null;
	}

	private static DnOut tonghuashunniu(List<Card> cards) {
		boolean tonghua=true;
		int hua=cards.get(0).getCardColor();
		for(Card card:cards) {
			if(card.getCardColor()!=hua) {
				tonghua=false;
				break;
			}
		}
		if(tonghua) {
			Map<Integer,Integer> numMap=numMap(cards);
			if(numMap.size()==cards.size()) {
				List<Integer> nums=new ArrayList<>();
				nums.addAll(numMap.keySet());
				List<List<Integer>> list=shun(nums, 5);
				if(!list.isEmpty()) {
					return new DnOut(SpecialNiu.TONGHUASHUN_NIU, cards);
				}
			}
		}
		
		return null;
	}

	public static Map<Integer,Integer> numMap(List<Card> list) {
		Map<Integer,Integer> numMap=new HashMap<Integer, Integer>();
		for(Card card:list) {
			int num=card.getCardNum();
			if(!numMap.containsKey(num)) {
				numMap.put(num, 1);
			}else {
				int old=numMap.get(num);
				numMap.put(num,old+1);
			}
		}
		return numMap;
	}
	
	
	public static List<KeyVal<Integer, Integer>> keyVals(List<Card> list) {
		Map<Integer,Integer> numMap=numMap(list);
		List<KeyVal<Integer, Integer>> result=new ArrayList<>();
		for(Entry<Integer,Integer> entry:numMap.entrySet()) {
			result.add(new KeyVal<Integer, Integer>(entry.getKey(), entry.getValue()));
		}
		return result;
	}
	
	private static List<List<Integer>> shun(List<Integer> tmp,int size) {
		List<List<Integer>> list = new ArrayList<>();
		List<Integer> unique_cardids=new ArrayList<>();
		for(Integer i:tmp) {
			if(unique_cardids.contains(i)) {
				continue;
			}
			unique_cardids.add(i);
		}
		Collections.sort(unique_cardids);
		for (int i = 0; i < unique_cardids.size(); i++) {
			List<Integer> out = new ArrayList<>();
			Integer card0 = unique_cardids.get(i);
			out.add(card0);
			for (int j = i + 1; j < unique_cardids.size(); j++) {
				Integer card1 = unique_cardids.get(j);
				if (card1 - card0 == j - i) {
					out.add(card1);
					if (out.size() >= size) {
						if (!list.contains(out)) {
							List<Integer> tt = new ArrayList<>();
							tt.addAll(out);
							list.add(tt);
						}
					}
				} else {
					out.clear();
					break;
				}
			}
		}
		return list;
	}
	
	public static int compareMaxCard(PlayerData banker_data, PlayerData playerData) {
		List<Card> banker_cards=new ArrayList<>();
		List<Card> other_cards=new ArrayList<>();
		banker_cards.addAll(banker_data.getDnOut().getCards());
		other_cards.addAll(playerData.getDnOut().getCards());
		Collections.sort(banker_cards,new Comparator<Card>() {

			@Override
			public int compare(Card o1, Card o2) {
				int num1=o1.getCardNum();
				if(num1==ER_VAL) {
					num1=2;
				}
				if(num1==A_VAL) {
					num1=1;
				}
				
				int num2=o2.getCardNum();
				if(num2==ER_VAL) {
					num2=2;
				}
				if(num2==A_VAL) {
					num2=1;
				}
				int result=num2-num1;
				if(result==0) {
					result=o2.getCardColor()-o1.getCardColor();
				}
				return result;
			}
		});
		
		Collections.sort(other_cards,new Comparator<Card>() {

			@Override
			public int compare(Card o1, Card o2) {
				int num1=o1.getCardNum();
				if(num1==ER_VAL) {
					num1=2;
				}
				if(num1==A_VAL) {
					num1=1;
				}
				
				int num2=o2.getCardNum();
				if(num2==ER_VAL) {
					num2=2;
				}
				if(num2==A_VAL) {
					num2=1;
				}
				int result=num2-num1;
				if(result==0) {
					result=o2.getCardColor()-o1.getCardColor();
				}
				return result;
			}
		});
		Card banker_max=banker_cards.get(0);
		Card other_max=other_cards.get(0);
		if(banker_max.getCardNum()>other_max.getCardNum()) {
			return banker_data.getUid();
		}else if(banker_max.getCardNum()==other_max.getCardNum()){
			if(banker_max.getCardColor()>other_max.getCardColor()) {
				return banker_data.getUid();
			}else {
				return playerData.getUid();
			}
		}else {
			return playerData.getUid();
		}
	}

	public static List<Card> findCardsByCardId(List<Card> list, List<Integer> cardIds) {
		List<Card> cards=new ArrayList<>();
		for(Integer cardId:cardIds) {
			cards.add(findCard(list,cardId));
		}
		return cards;
	}

	private static Card findCard(List<Card> list, Integer cardId) {
		for(Card card:list) {
			if(card.getCardId()==cardId) {
				return card;
			}
		}
		return null;
	}

}
